#include "WaveRender.h"

WaveRender::WaveRender(const std::string& name):IRender(name)
{
	mVertex = ShaderManager::Instance()->CreateShader(SID_WAVE_VERTEX);
	ShaderManager::Instance()->LoadShader(mVertex);
	mVertexProgram = ShaderManager::Instance()->GetProgram(mVertex);
	mParamMvp = cgGetNamedParameter(mVertexProgram, "mvp");
	//mParamWorldMatrix = cgGetNamedParameter(mVertexProgram, "worldMatrix");
	//mOutColor = cgGetNamedParameter(mVertexProgram, "outColor");

	mEyePosition[0] = 0;
	mEyePosition[1] = 18;
	mEyePosition[2] = 12;

	CGparameter eyePosition = cgGetNamedParameter(mVertexProgram, "eyePosition");
	cgSetParameter3fv(eyePosition, mEyePosition);

	mFragment = ShaderManager::Instance()->CreateShader(SID_WAVE_FRAGMENT);
	ShaderManager::Instance()->LoadShader(mFragment);
	mFragmentProgram = ShaderManager::Instance()->GetProgram(mFragment);

	glMatrixMode(GL_PROJECTION);
	gluPerspective(60, 1, 1, 100);
	glGetFloatv(GL_PROJECTION_MATRIX, mProject);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(mEyePosition[0], mEyePosition[1], mEyePosition[2], 0, 0, 0, 0, 1, 0);
	glGetFloatv(GL_MODELVIEW_MATRIX, mView);

	mRotateAngleY = 0;

	m_pkVertexs = NULL;
	m_pkIndexes = NULL;
	m_Wn = m_Hn = 0;
	init_wave(1.0f, 1.0f, 20, 10);
}

void WaveRender::draw()
{
	ShaderManager::Instance()->BindShader(mVertex);
	ShaderManager::Instance()->EnableShaderProfile(mVertex);
	ShaderManager::Instance()->BindShader(mFragment);
	ShaderManager::Instance()->EnableShaderProfile(mFragment);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glGetFloatv(GL_MODELVIEW_MATRIX, mModel);

	glLoadMatrixf(mProject);
	glMultMatrixf(mView);
	glMultMatrixf(mModel);
	glGetFloatv(GL_MODELVIEW_MATRIX, mModelViewProject);

	cgSetMatrixParameterfr(mParamMvp, mModelViewProject);
	//cgSetMatrixParameterfr(mParamWorldMatrix, mModel);
	//cgSetParameter3f(mOutColor, 0, 1, 0);

	draw_wave();

	ShaderManager::Instance()->UnBindShader(mFragment);
	ShaderManager::Instance()->DisableShaderProfile(mFragment);
	ShaderManager::Instance()->UnBindShader(mVertex);
	ShaderManager::Instance()->DisableShaderProfile(mVertex);
}

void WaveRender::idle()
{
	mRotateAngleY += 1.0f;
	if (mRotateAngleY >= 360.0f)
	{
		mRotateAngleY -= 360.0f;
	}
}

void WaveRender::draw_wave()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	glEnableClientState(GL_VERTEX_ARRAY);
	//glEnableClientState(GL_INDEX_ARRAY);

	glVertexPointer(3, GL_FLOAT, 0, m_pkVertexs);

	for (int i = 0; i < m_Hn - 1; ++i)
	{
		glDrawElements(GL_TRIANGLE_STRIP, m_Wn * 2, GL_UNSIGNED_INT, m_pkIndexes + m_Wn * 2 * i);
	}

	//glDisableClientState(GL_INDEX_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

void WaveRender::init_wave(float w, float h, int wn, int hn)
{
	m_Hn = hn;
	m_Wn = wn;
	float gw = (wn - 1) * w * 0.5f;
	float gh = (hn - 1) * h * 0.5f;
	m_pkVertexs = new GLfloat[wn * hn * 3];
	m_pkIndexes = new GLuint[2 * wn * (hn - 1)];
	int iIndexCnt = 0;
	for (int i = 0; i < hn; ++i)
	{
		for (int j = 0; j < wn; ++j)
		{
			int index = i * wn + j;
			m_pkVertexs[3 * index + 0] = w * j - gw;
			m_pkVertexs[3 * index + 1] = 0;
			m_pkVertexs[3 * index + 2] = h * i - gh;

			if (i + 1 < hn)
			{
				m_pkIndexes[iIndexCnt] = index; ++iIndexCnt;
				m_pkIndexes[iIndexCnt] = index + wn; ++iIndexCnt;
			}
		}
	}
}